package com.phantasy.caches
{
	import com.phantasy.globals.GameParameters;
	import com.phantasy.ui.UISystem;
	
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.utils.ByteArray;

	/**
	 *缓存加载器用于如果开启缓存加载机制的话会将数据缓存到本地的SO对象中.
	 * @author Liseen
	 * 
	 */	
	public class CacheLoader extends EventDispatcher
	{
		
		private var _loader:Loader;
		private var _urlLoader:URLLoader;
		private var _lc:LoaderContext;
		private var _url:String;
		private var _urlKey:String;
		private var _retryCount:int=0;
		private var _maxRetryCount:int=3;
		
		public var datas:ByteArray;
		public var bytesLoaded:uint;
		public var bytesTotal:uint;
		
		public function CacheLoader()
		{
			super();
			
			this._loader = new Loader();
			this._urlLoader = new URLLoader();
			this._urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			this.addEventListeners();
		}
		
		/**
		 *获取Loader对象 
		 * @return 
		 * 
		 */		
		public function getLoader():Loader
		{
			if(this._loader!=null){
				return this._loader;
			}
			
			return null;
		}
		/**
		 *获取LoaderInfo对象 
		 * @return 
		 * 
		 */		
		public function get contentLoaderInfo():LoaderInfo
		{
			return this._loader.contentLoaderInfo;
		}
		/**
		 *卸载 
		 * 
		 */		
		public function unLoad():void
		{
			this._loader.unload();	
		}
		/**
		 *关闭加载 
		 * 
		 */		
		public function close():void
		{
			this._loader.close();
			this._urlLoader.close();	
		}
		/**
		 *销毁 
		 * 
		 */		
		public function dispose():void
		{
			removeEventListeners();
			this._loader=null;
			this._urlLoader=null;
		}
		/**
		 *加载 
		 * @param request			请求对象
		 * @param debugMode			是否为debug模式
		 * @param loaderContext		加载器上下文环境
		 * 
		 */		
		public function load(request:URLRequest,debugMode:Boolean=false,loaderContext:LoaderContext=null):void
		{
			this._lc = loaderContext;
			
			if(request.url.indexOf("?")==-1){
				request.url = request.url+"?v"+UISystem.v;
			}
			
			this._urlKey = request.url;
			if(debugMode){
				
				this._url = request.url;
				
			}else{
				this._url = GameParameters.getInstance().resourceHost+"/"+request.url;
				request.url = this._url;
			}
			
			if(CacheManager.getInstance().allowCache&&!debugMode){
				
				CacheManager.getInstance().readFile(this._urlKey, this.readCompleteHandler);
				
			}else{
				
				this._urlLoader.load(request);
			}
			
		}
		
		/**
		 *处理缓存读取 
		 * @param data
		 * 
		 */		
		private function readCompleteHandler(data:ByteArray):void
		{
			if(data==null){
				_urlLoader.load(new URLRequest(this._url));
			}else{
				_loader.loadBytes(data,this._lc);
			}
		}
		
		
		/**
		 *添加事件侦听 
		 * 
		 */		
		private function addEventListeners():void
		{
			this._loader.contentLoaderInfo.addEventListener(Event.COMPLETE,	onloaderCompleteHandler);
			this._loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityErrorHandle);
			this._loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,onProgressHandler);
			this._loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,onIOErrorHandle);
			
			_urlLoader.addEventListener(Event.COMPLETE,onURLLoaderCompleteHandle);
			_urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityErrorHandle);
			_urlLoader.addEventListener(ProgressEvent.PROGRESS,onProgressHandler);
			_urlLoader.addEventListener(IOErrorEvent.IO_ERROR,onIOErrorHandle);
		}
		/**
		 *移除事件侦听 
		 * 
		 */		
		private function removeEventListeners():void
		{
			this._loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,	onloaderCompleteHandler);
			this._loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityErrorHandle);
			this._loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,onProgressHandler);
			this._loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,onIOErrorHandle);
			
			_urlLoader.removeEventListener(Event.COMPLETE,onURLLoaderCompleteHandle);
			_urlLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityErrorHandle);
			_urlLoader.removeEventListener(ProgressEvent.PROGRESS,onProgressHandler);
			_urlLoader.removeEventListener(IOErrorEvent.IO_ERROR,onIOErrorHandle);
		}
	
		private function onloaderCompleteHandler(event:Event):void
		{
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		private function onURLLoaderCompleteHandle(event:Event):void
		{
			var cacheData:ByteArray;
			this.datas = this._urlLoader.data as ByteArray;
			if(CacheManager.getInstance().allowCache&&this._urlKey!=""){
				cacheData = CacheManager.getInstance().isExistResource(this._urlKey);
				if(cacheData==null){
					CacheManager.getInstance().writeFile(this._urlKey,this.datas);
				}
			}
			
			if(this.datas){
				this._loader.loadBytes(this.datas,this._lc);
			}
			
		}
		
		private function onSecurityErrorHandle(event:SecurityErrorEvent):void
		{
			if(this._retryCount>=this._maxRetryCount){
				
				this.dispatchEvent(event);
				
			}else{
				this._retryCount++;
				this._urlLoader.load(new URLRequest(this._url));
			}
		}
		
		private function onProgressHandler(event:ProgressEvent):void
		{
			this.bytesLoaded = event.bytesLoaded;
			this.bytesTotal = event.bytesTotal;
			dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS));
		}
		
		private function onIOErrorHandle(event:IOErrorEvent):void
		{
			if(this._retryCount>=this._maxRetryCount){
				
				this.dispatchEvent(event);
				
			}else{
				this._retryCount++;
				this._urlLoader.load(new URLRequest(this._url));
			}
		}
	}
}